package particles;

class Particle2
{
	public var moveToTarget : Bool;
	
	public var age : Float;
	public var ageDead : Int;
	
	public var xTarget : Float;
	public var yTarget : Float;
	
	public var x : Float;
	public var y : Float;
	
	public var windX : Float;
	public var windY : Float;
	
	public var xVelocity : Float;
	public var yVelocity : Float;
	
	public var angle : Float;
	public var angleVelocity : Float;
	public var angleTarget : Float;

	public var r : Int;
	public var g : Int;
	public var b : Int;
	
	public var rnd1 : Float;
	public var rnd2 : Float;
	public var rnd3 : Float;
	
	public var form : Int;
	
	public var width : Int;
	public var height : Int;
	
	public var attractMouse : Bool;
	
	public function new()
	{
		attractMouse = false;
	}
	
	public function reset(model : EngineModel)
	{
		this.width = model.width;
		this.height = model.height;

		rnd1 = Math.random();
		rnd2 = Math.random();
		rnd3 = Math.random();
		
		var index = Std.int(Math.random() * 100);
		var ti = Math.sin(model.time / 100 + index / 30);
		
		r = Std.int((Math.sin(model.time / 1000) / 2 + 0.5) * 200) + 55;
		g = Std.int((Math.sin(model.time / 2000 + 0.3) / 2 + 0.5) * 200) + 55;
		b = Std.int(((ti + Math.sin(model.time / 300 + 0.7)) / 4 + 0.5) * 200) + 55;
		
		x = model.width + ti * 100 + Math.sin(model.time / 2400 + 0.5) * model.width * 0.5;
		y = model.height + Math.cos(model.time / 110 + index / 35) * 50 + Math.sin(model.time / 3000) * model.height * 0.5;
		
		computeWind(model.time);
		
		var rnd = Math.random();
		if (rnd < 0.3)
			angle = Math.atan2(windY, windX);
		else if (rnd < 0.6)
			angle = -Math.atan2(windY, windX);
		else
			angle = Math.atan2(windY, windX);
			
		angleVelocity = Math.sin(-windX) * 0.1 - Math.random() * 0.03 - 0.07;
		angleTarget = 0.9;

		xVelocity = windX * 5;
		yVelocity = windY * 5;
		
		xVelocity = 0;
		yVelocity = 0;
		
		age = 0;
		ageDead = 30 * 7;
		
		var formRnd = (Math.sin(model.time / 2000) + ti) / 4 + 0.5;
		
		if (Math.random() < 0.3)
			formRnd = Math.random();
			 
		if (formRnd < 0.4)
			form = 0;
		else if (formRnd < 0.8)
			form = 1;
		else if (formRnd < 0.9)
			form = 2;
		else
			form = 3;
	}
	
	public function update(model : EngineModel)
	{
		moveToTarget = Math.cos(model.time / 7000 + 0.4 + rnd1 * 0.8) > 0.4;
		
		if (moveToTarget)
		{
			var targetForm = Math.cos(model.time / 9000 + 0.4 + rnd1 * 0.8);
			
			if (targetForm < -0.3)
			{
				//half circle
				var targetRad = rnd1 * 1 * Math.PI;
				var radius = width * 0.4;
				xTarget = Math.sin(targetRad) * radius + width;
				yTarget = Math.cos(targetRad) * radius + height;
			}
			else if (targetForm < 0.4)
			{
				//line
				var targetRad = rnd1 * 2 * Math.PI;
				var radius = width * 1;
				xTarget = Math.sin(targetRad) * radius + width;
				yTarget = height;
			}
			else
			{
				//parabel
				var targetRad = rnd1 * 100 * Math.PI;
				var radius = width * 0.5;
				xTarget = Math.sin(targetRad / 2) * radius + width;
				yTarget = Math.sin(targetRad + Math.PI / 2) * radius / 2 + height;
			}
			
			age += 0.5;
		}
		else
		{
			age += (Math.sin(model.time / 5000) / 2 + 0.5) * 2 + 0.5;
		}
		
		if (moveToTarget)
		{
			var dx = (xTarget - x);
			var dy = (yTarget - y);
			var dLen = Math.sqrt(dx * dx + dy * dy);
			var dx2 = dx / dLen;
			var dy2 = dy / dLen;
			angleTarget = Math.atan2(dy2, dx2);
		}
		
		if (attractMouse)
		{
			var dx = (model.mouseX * 2 - x);
			var dy = (model.mouseY * 2 - y);
			var dLen = Math.sqrt(dx * dx + dy * dy);
		
			if (dLen < 300)
			{
				var dx2 = dx / dLen;
				var dy2 = dy / dLen;
				angleTarget = Math.atan2(dy2, dx2);
			}
		}
		
		while (angle > Math.PI)
			angle -= Math.PI * 2;
		while (angle < -Math.PI)
			angle += Math.PI * 2;

		while (angleTarget > Math.PI)
			angleTarget -= Math.PI * 2;
		while (angleTarget < -Math.PI)
			angleTarget += Math.PI * 2;

		var dAngle = angleTarget - angle;

		while (dAngle > Math.PI)
			dAngle -= Math.PI * 2;
		while (dAngle < -Math.PI)
			dAngle += Math.PI * 2;

		if (moveToTarget)
			angleVelocity += dAngle * 0.05;
		else
			angleVelocity += dAngle * 0.001;
		angle += angleVelocity;
		
		xVelocity += Math.cos(angle) * 0.2 * (rnd3 + 0.5);
		yVelocity += Math.sin(angle) * 0.2 * (rnd3 + 0.5);
		
		computeWind(model.time);
		
		angleVelocity -= windX * 0.001;
		
		xVelocity += windX * 0.2 * (rnd2 / 2 + 0.3);
		yVelocity += windY * 0.2 * (rnd2 / 2 + 0.3);
		
		if (moveToTarget)
		{
			var dx = (xTarget - x);
			var dy = (yTarget - y);
			var dLen = Math.sqrt(dx * dx + dy * dy);
			dx /= dLen;
			dy /= dLen;
			
			if (dLen > 100)
				dLen = 100;
				
			dLen = Math.pow(dLen, 1.7);
				
			dx *= dLen * 0.0003 * (rnd2 / 2 + 0.3);
			dy *= dLen * 0.0003 * (rnd2 / 2 + 0.3);
			
			xVelocity += dx;
			yVelocity += dy;
		}
		
		if (attractMouse)
		{
			var dx = (model.mouseX * 2 - x);
			var dy = (model.mouseY * 2 - y);
			var dLen = Math.sqrt(dx * dx + dy * dy);
			dx /= dLen;
			dy /= dLen;
			
			if (dLen > 200)
				dLen = 200;

			dLen = Math.pow(200 - dLen, 1.7);
				
			dx *= dLen * 0.0003 * rnd1;
			dy *= dLen * 0.0003 * rnd1;
			
			xVelocity += dx;
			yVelocity += dy;
		}

		if (moveToTarget)
		{
			angleVelocity *= 0.90;
			xVelocity *= 0.92;
			yVelocity *= 0.92;
		}
		else
		{
			angleVelocity *= 0.999;
			xVelocity *= 0.985;
			yVelocity *= 0.985;
		}
		
		x += xVelocity;
		y += yVelocity;
		
		// form = 0;
		// x = 200;
		// y = 800 - 300;
		// angle = 0.3;		
	}
	
	private inline function computeWind(time : Float)
	{
		windX = Math.sin(time / 600 + x / 200 + y / 250) * 0.3;
		windY = Math.sin(time / 700 + Math.PI / 5 + x / 40 + y / 100) * 0.3;
	}
}